﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace JSIF_WCFServer.VersionControl
{
    /// <summary>
    /// An abstraction over a method of versioning a folder
    /// </summary>
    public interface IVersionControl
    {
        /// <summary>
        /// Returns a writeable instance of the head revision
        /// </summary>
        /// <param name="root">the root folder</param>
        /// <returns>a writeable instance of the head revision</returns>
        IWriteableVersionControlInstance GetRootAtHead(String root);

        /// <summary>
        /// Returns a readonly instance of a past revision
        /// </summary>
        /// <param name="root">the root folder</param>
        /// <param name="version">the version number</param>
        /// <returns>A readonly instance of a past revision</returns>
        IReadOnylVersionControlInstance GetRootAtVersion(String root, int version);

        /// <summary>
        /// Tells the version control instance that it can now reclaim and reuse any resources which were being held by the specified instance
        /// </summary>
        /// <param name="versionControlInstance">The instance to return to the pool</param>
        void ReturnInstance(IReadOnylVersionControlInstance versionControlInstance);

        /// <summary>
        /// Creates a new root
        /// </summary>
        /// <remarks>
        /// Calling this on an existing root should return the root to the "new" state, as if there was no existing book prior to the call.  There can be no naming restrictions, if necessary the version control implementation must map specified root names to an internale naming scheme transparently
        /// </remarks>
        /// <param name="root">the root folder</param>
        /// <param name="comment">a comment to associate with this change</param>
        /// <returns>true if the operation was successfull</returns>
        bool CreateRoot(String root, String comment);
        /// <summary>
        /// Renames an existing root to something else
        /// </summary>
        /// <remarks>
        /// This is equivalent to calling "CopyRoot rootSource rootDest" followed by "DeleteRoot routeSource"
        /// </remarks>
        /// <param name="rootSource">the source root</param>
        /// <param name="rootDest">the destination root</param>
        /// <param name="comment">a comment to associate with this change</param>
        /// <returns>true if the operation was successfull</returns>
        bool RenameRoot(String rootSource, String rootDest, String comment);
        /// <summary>
        /// Copies one root to another
        /// </summary>
        /// <remarks>
        /// If the destination root already existed, it would be replaced completly by the source as if there was nothing there previously.
        /// </remarks>
        /// <param name="rootSource">the source root</param>
        /// <param name="rootDest">the destination root</param>
        /// <param name="comment">a comment to associate with this change</param>
        /// <returns>true if the operation was successfull</returns>
        bool CopyRoot(String rootSource, String rootDest, String comment);

        /// <summary>
        /// Deletes the specified root
        /// </summary>
        /// <param name="root">the root to delete</param>
        /// <param name="comment">a comment to associate with this change</param>
        /// <returns>true if the operation was successfull</returns>
        bool DeleteRoot(String root, String comment);
 
        /// <summary>
        /// Returns the history for the specified folder with the most recent changes listed first
        /// </summary>
        /// <param name="root">the root folder</param>
        /// <returns>the history for the specified folder with the most recent changes listed first</returns>
        IEnumerable<String> GetHistory(String root);

        /// <summary>
        /// Returns the list of root folders in this version controller
        /// </summary>
        /// <returns>the list of root folders in this version controller</returns>
        IEnumerable<String> GetRoots();
    }
    public interface IReadOnylVersionControlInstance
    {
        /// <summary>
        /// Returns the names of the files present in the folder at the specified version
        /// </summary>
        /// <returns>the names of the files present in the folder at the specified version</returns>
        IEnumerable<String> GetFileNames();

        /// <summary>
        /// Returns the contents of the specified file
        /// </summary>
        /// <param name="root">the root folder</param>
        /// <param name="version">the version to fetch</param>
        /// <param name="filename">the nameof the file to fetch</param>
        /// <returns>the contents of the specified file</returns>
        byte[] GetFile(String filename);
    }
    public interface IWriteableVersionControlInstance : IReadOnylVersionControlInstance
    {
        /// <summary>
        /// Updates the working copy to the latest revision
        /// </summary>
        /// <returns>true if the operation was successful</returns>
        bool Update();

        /// <summary>
        /// Commits any changes to the working copy
        /// </summary>
        /// <param name="comment">A comment to associate with the changes</param>
        /// <returns>true if the operation was successful</returns>
        bool Commit(String comment);

        /// <summary>
        /// Puts a file into the root
        /// </summary>
        /// <remarks>
        /// There can be no filename restrictions. If necessary the version control must maintain a mapping between the specified names and any internal naming scheme transparently.
        /// </remarks>
        /// <param name="root">the root folder</param>
        /// <param name="filename">the name of the file</param>
        /// <param name="contents">the contents of the file</param>
        /// <param name="comment">a comment to associate with this change</param>
        /// <returns>true if the operation was successfull</returns>
        bool PutFile(String filename, byte[] contents);
        /// <summary>
        /// Deletes the specified file
        /// </summary>
        /// <param name="filename">the name of the file</param>
        /// <returns>true if the operation was successfull</returns>
        bool DeleteFile(String filename);
        /// <summary>
        /// Renames a file
        /// </summary>
        /// <remarks>
        /// If the destination file already existed it will be overwritten
        /// </remarks>
        /// <param name="filenameSource">the original name of the file</param>
        /// <param name="filenameDest">the new name of the file</param>
        /// <returns>true if the operation was successfull</returns>
        bool RenameFile(String filenameSource, String filenameDest);
        /// <summary>
        /// Copies a file
        /// </summary>
        /// <remarks>
        /// If the destination file already existed it will be overwritten
        /// </remarks>
        /// <param name="filenameSource">the source file</param>
        /// <param name="filenameDest">the destination file</param>
        /// <returns>true if the operation was successfull</returns>
        bool CopyFile(String filenameSource, String filenameDest);
    }
}
